home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Trading on the Edge
/
Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin
/
pc
/
mac_file
/
vendor_d
/
azte_pro
/
human.c
< prev
next >
Wrap
Text File
|
1993-06-11
|
33KB
|
1,521 lines
/* 10/24/89.
* Human player for the Double Oral Auction Tournament.
* C version. R.G. Palmer, Jan-Apr 1989.
*
* This is based on the standard C skeleton player, but asks the user
* what to do at each stage. It also has help facilities and options
* to display past history etc.
*
* This must be linked with the result of compiling the control routines
* in control.c. You must customize the definitions in the define.h
* header file AND the definitions below before compiling.
*
* See README for compilation instructions.
*
*---------------History mechanism------------------------------------
* HISTORY may be defined to enable the 'history' mechanism for a
* human player.
* The history mechanism is accessed by typing h at a prompt and
* produces a display of the recent history of the game.
* It uses extra memory, and extra I/O time if FILEBASED.
*
* MAXHIST specifies how far back the history should be kept. Use 3
* less than the number of screen lines on a non-scrollable terminal.
* The extra memory and I/O time increase for larger MAXHIST.
*
* Define AUTOHIST to be the number of lines of history to be shown
* automatically at each step. Set to 0 for none. Use up to 7 less
* than the number of screen lines on a non-scrollable terminal.
*
* MAXHIST and AUTOHIST are ignored if HISTORY is not set. 13 and 9
* are recommended for a Macintosh with Lightspeed C 4.0.
*/
#define HISTORY 1
#define MAXHIST 21
#define AUTOHIST 0
/*---------------Timeout and '.' display------------------------------
* Define TIMEOUT for a human player if you want the program to default
* your replies if you don't respond within a certain time. The default
* is equivalent to you just pressing RETURN. The time allowed is
* approximately 2/3 of the monitor's 'timeout' value (read from the game
* file). The user can turn the timeout mechanism off or on with the w and
* -w commands.
*
* Define DOTS if you want dots (.) to be displayed every second during
* the waiting period, with colons (:) in the last five seconds.
*
* Define INTRCHAR to be the integer value of your interrupt character.
* If TIMEOUT is defined, your program has to do its own interrupt
* processing because a raw mode read is used. Common values include
* 3 for cntl-C, 24 for cntl-X, 25 for cntl-Y, and 127 for DEL.
* If you don't define it a default value will be used (cntl-C for
* most systems, '.' for Macintosh).
*
* If you don't define TIMEOUT, the timeout mechanism will be disabled
* and w and -w will have no effect. DOTS is then ignored.
* It may be worth trying this case if you have compilation or run-time
* problems associated with the non-blocking I/O used for input when
* TIMEOUT is defined.
* If the timeout mechanism is disabled (either by not defining TIMEOUT
* or with the w command), the monitor may timeout the player and send
* a **late** message next time it does respond.
*
* If you define TIME_OUT_BO and TIME_OUT_BS, the computer will use
* these values for timing out during the bid/offer and buy/sell steps,
* respectively, instead of 2/3 of the monitor's timeout value.
*/
#define TIMEOUT 1
#define DOTS 1
#define TIME_OUT_BO 10
#define TIME_OUT_BS 10
/*---------------Period notification----------------------------------
* Define BEEP if you want to be notified of the start of each period
* with a BEEP. This is particularly useful with multiple human players,
* when there may be a long period between the time that YOU can't make
* any more trades in a period and the actual end of that period.
*/
#define BEEP 1
/*---------------Headings--------------------------------------------
* Define HEADLINE if you want the time and token information to appear
* before buy-sell steps as well as bid-offer steps. Useful if you
* set AUTOHIST > 0, or if your screen gets cleared on every step.
*/
/* #define HEADLINE 1 */
/* ---------------------- end of customization ------------------------- */
#include "define.h"
#include <stdio.h>
#ifdef THINKC3
#include <strings.h>
#else
#include <strings.h>
#endif
/* List of global variables */
extern int nplayers;
extern int nbuyers;
extern int nsellers;
extern int bnumber[];
extern int snumber[];
extern int nrounds;
extern int nperiods;
extern int ntimes;
extern int minprice;
extern int maxprice;
extern int gameid;
extern int r;
extern int p;
extern int t;
extern int cbid;
extern int coffer;
extern int bidder;
extern int offerer;
extern int nbids;
extern int noffers;
extern int bids[];
extern int offers[];
extern int bstype;
extern int price;
extern int buyer;
extern int seller;
extern int btrades[];
extern int strades[];
extern int ntrades;
extern int prices[];
extern int lasttime;
extern int id;
extern int role;
extern int timeout;
extern int ntokens;
extern int token[];
extern int mytrades;
extern int mylasttime;
extern int pprofit;
extern int rprofit;
extern int gprofit;
extern int nobidoff;
extern int bo;
extern int nobuysell;
extern int bs;
extern int late;
extern int tradelist[];
extern int profitlist[];
extern int efficiency;
extern int noblock;
extern int waitforreturn;
int hmtype = 1; /* human player */
extern void error();
extern double drand();
extern void twolinehead(),showcurrent(),showprices(),nl();
/* system dependent includes, defines, etc. */
#ifndef DISPLAY
<<DISPLAY not defined>>
#endif
/* generic */
#ifdef UNIX
#define TERMIO 1
#endif
#ifdef BSD43
#define UNIX 1
#define TTY 1
#define FCNTL 1
#endif
#ifdef SUN3
#define UNIX 1
char * sprintf(); /* for lint */
#define TTY 1
#define FCNTL 1
#endif
#ifdef SUN4
#define UNIX 1
char * sprintf(); /* for lint */
#define TERMIOS 1
#endif
#ifdef CRAY
#define UNIX 1
#define TERMIO 1
#define FCNTL 1
#endif
#ifdef IRIS
#define UNIX 1
#define TERMIO 1
#endif
#ifdef TURBOC
#define MSDOS 1
#define DOS_OR_T3 1
#define ANSI 1
#endif
#ifdef QUICKC
#define MSDOS 1
#define DOS_OR_T3 1
#define ANSI 1
#include <time.h>
#endif
#ifdef THINKC3
#define THINKC 1
#define DOS_OR_T3 1
#endif
#ifdef THINKC4
#define THINKC 1
#define ANSI 1
#include <console.h>
#endif
#ifdef VMS
#define GOODEXIT 1
int queued = -1;
int dcl_chan = 0;
#ifdef TIMEOUT
#include <iodef.h>
#include <descrip.h>
struct ios_block {
short iostat,count;
int def_info;
};
#endif
#else
#define GOODEXIT 0
#endif
#ifdef ANSI
#include <stddef.h>
#ifndef NO_STDLIB_H
#include <stdlib.h>
#endif
#endif
#ifdef MSDOS
#include <conio.h>
#endif
#ifdef UNIX
#include <errno.h>
extern int errno;
#include <fcntl.h>
#include <sys/types.h> /* these four are for kbhit() */
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
#ifdef TIMEOUT
#define UNOBLOCK 1
#endif
#endif
#ifdef UNOBLOCK
#ifdef TERMIOS
#include <sys/termios.h>
typedef struct termios termstruct;
#define GETTERM TCGETS
#define SETTERM TCSETSF
#endif
#ifdef TERMIO
#include <sys/termio.h>
typedef struct termio termstruct;
#define GETTERM TCGETA
#define SETTERM TCSETAF
#endif
#ifdef TTY
#ifdef CRAY
#include <sys/ioctl.h>
#else
#include <sgtty.h> /* may need to be <ioctl.h> on some systems */
#endif /* CRAY */
typedef struct sgttyb termstruct;
static int one = 1;
#define GETTERM TIOCGETP
#define SETTERM TIOCSETP
#endif
#endif
#ifndef INTRCHAR
#ifdef THINKC
#define INTRCHAR '.'
#else
#define INTRCHAR 3
#endif
#endif
/* local routines */
static void bohelp(),bshelp();
static char * ask();
static int ready();
static char * response();
static void getreply();
#ifdef TIMEOUT
static void putnflush();
static int termchar();
#endif
static void incorrect(),help(),showhist();
void setnoblock(),resetterm(); /* used by control.c */
#ifdef QUICKC
static void sleep();
#endif
/* standard #defines, and some more */
#define MAXPLAYERS 20
#define MAXROUNDS 20
#define MAXPERIODS 5
#define MAXTIMES 400
#define MAXTOKENS 4 /* don't change */
#define ROLES 3
#define PLAYERNUMBER 9999 /* always use 9999 for human */
#define EOS '\0'
#define BELL 07
#define BS 010
#define DEL 0177
#define LINESIZE 82
/* local variables */
int passflag = 0; /* flag for p (pass) option */
int fastflag = 0; /* flag for f (fast) option */
int waitflag = 0; /* flaf for w (wait) option */
int unwise=0; /* flag for unwise mode */
int yes = 0; /* flag for yes mode */
char linebuf[LINESIZE]; /* line buffer for I/O */
char newline[] = "\n";
char none[] = "\0";
int timeleft = 0; /* countdown timer */
/* the history list and associated variables and flag bits */
#ifdef HISTORY
unsigned int histlist[MAXHIST][MAXDISPLAY];
int tlist[MAXHIST];
int last = (-1);
#define BUYCHAR '<'
#define SELLCHAR '>'
#define BOMASK 8191
#define CURRENT 8192
#define BFLAG 16384
#define SFLAG 32768
#define TIMEMASK 1023
#define NOBOHIST 1024
#define NOBSHIST 2048
#endif
/* auxiliary routines */
void gbegin() {}
void gend() {}
void rbegin() {}
void rend() {}
void pend() {}
/* pbegin -- called at the start of each period */
void
pbegin()
{
#ifdef BEEP
putc(BELL,stderr);
fflush(stderr);
sleep(2); /* just for aesthetics */
#endif
passflag = 0;
#ifdef HISTORY
last = (-1); /* clear history list */
#endif
}
/* boend -- called at the end of every bid-offer step */
void
boend()
{
#ifdef HISTORY
register int i;
int l;
unsigned int * hist;
#endif
if (bo == -2)
showcurrent();
#ifdef HISTORY
l = ++last % MAXHIST;
if (bo == -2)
tlist[l] = NOBSHIST; /* time unknown, no bs info yet */
else
tlist[l] = t|NOBSHIST;
hist = histlist[l];
for (i=1; i<=nbuyers; i++) {
hist[i-1] = bids[i];
if (i == bidder)
hist[i-1] |= CURRENT;
}
hist += nbuyers;
for (i=1; i<=nsellers; i++) {
hist[i-1] = offers[i];
if (i == offerer)
hist[i-1] |= CURRENT;
}
showhist(AUTOHIST);
#endif
#ifdef HEADLINE
twolinehead();
#endif
}
/* bsend -- called at the end of every buy-sell step */
void
bsend()
{
#ifdef HISTORY
register int i;
unsigned int * hist;
int l;
l = last % MAXHIST;
if (bs == -2) { /* late */
l = ++last % MAXHIST;
tlist[l] = NOBOHIST; /* time unknown, no bo info */
hist = histlist[l];
for (i=1; i<=nbuyers; i++)
hist[i-1] = 0;
for (i=1; i<=nsellers; i++)
hist[nbuyers+i-1] = 0;
if (bstype == 1) hist[nbuyers+seller-1] = price|CURRENT;
if (bstype == 2) hist[buyer-1] = price|CURRENT;
}
else
tlist[l] = (tlist[l]|t)&(~NOBSHIST);
hist = histlist[l];
switch (bstype) {
case 1:
hist[buyer-1] |= BFLAG;
hist[nbuyers+seller-1] |= BFLAG;
break;
case 2:
hist[buyer-1] |= SFLAG;
hist[nbuyers+seller-1] |= SFLAG;
break;
default:
break;
}
showhist(AUTOHIST);
#endif
}
/* bid -- called in every bid-offer step if we're playing a buyer.
* Must return bid value or 0. Must return 0 if nobidoff>0.
*/
int
bid()
{
int nexttoken;
int newbid;
char * reply;
#ifdef TIME_OUT_BO
timeleft = TIME_OUT_BO;
#else
timeleft = timeout*2/3;
#endif
if (nobidoff>0) {
while (!ready("nothing to trade")) ;
return (0);
}
nexttoken = token[mytrades+1];
while(1) {
if (cbid>=nexttoken-1 && unwise) {
if (ready("unwise to bid"))
return (0);
else
continue;
}
reply = ask("bid [n]");
if (*reply == EOS) continue;
if (*reply == '\n'|| *reply == 'n')
return (0);
if (sscanf(reply,"%d",&newbid) != 1) {
if (*reply != '?') incorrect(reply);
bohelp("bid");
continue;
}
if (newbid<minprice || newbid>maxprice)
printf("%cInvalid bid!\nYou must bid in the range %d-%d",
BELL,minprice,maxprice);
else if (newbid<=cbid)
printf("%cInvalid bid!\nYou must bid above the current bid of %d",
BELL,cbid);
else if (newbid>=nexttoken && unwise)
printf(
"%cUnwise bid!\nYou should bid below your next token of %d",BELL,nexttoken);
else
return (newbid);
puts(", or press RETURN to pass.");
}
/*NOTREACHED*/
}
/* offer -- called in every bid-offer step if we're playing a seller.
* Must return offer value or 0. Must return 0 if nobidoff>0.
*/
int
offer()
{
int nexttoken;
int newoffer;
char * reply;
#ifdef TIME_OUT_BO
timeleft = TIME_OUT_BO;
#else
timeleft = timeout*2/3;
#endif
if (nobidoff>0) {
while (!ready("nothing to trade")) ;
return (0);
}
nexttoken = token[mytrades+1];
while(1) {
if (coffer>0 && coffer<=nexttoken+1 && unwise) {
if (ready("unwise to offer"))
return (0);
else
continue;
}
reply = ask("offer [n]");
if (*reply == EOS) continue;
if (*reply == '\n' || *reply == 'n')
return (0);
if (sscanf(reply,"%d",&newoffer) != 1) {
if (*reply != '?') incorrect(reply);
bohelp("offer");
continue;
}
if (newoffer == 0) return (0);
if (newoffer<minprice || newoffer>maxprice)
printf("%cInvalid offer!\nYou must offer in the range %d-%d",
BELL,minprice,maxprice);
else if (coffer>0 && newoffer>=coffer)
printf(
"%cInvalid offer!\nYou must offer below the current offer of %d",
BELL,coffer);
else if (newoffer<=nexttoken && unwise)
printf(
"%cUnwise offer!\nYou should offer above your next token of %d",BELL,nexttoken);
else
return (newoffer);
puts(", or press RETURN to pass.");
}
/*NOTREACHED*/
}
/* buy -- called in every buy-sell step if we're playing a buyer.
Must return 1 to request a buy, or 0 to pass.
Must return 0 if nobuysell>0. */
int
buy()
{
int nexttoken;
char * reply;
char prompt[15];
#ifdef TIME_OUT_BS
timeleft = TIME_OUT_BS;
#else
timeleft = timeout*2/3;
#endif
if (nobuysell&1) {
while (!ready("nothing to trade")) ;
return (0);
}
if (nobuysell&2) {
while (!ready("nothing to buy")) ;
return (0);
}
if (nobuysell&4) {
while (!ready("not bidder")) ;
return (0);
}
nexttoken = token[mytrades+1];
while(1) {
if (nexttoken<=coffer && unwise) {
if (ready("unwise to buy"))
return (0);
else
continue;
}
sprintf(prompt,"buy at %d [%c]",coffer,yes?'y':'n');
reply = ask(prompt);
if (*reply == EOS) continue;
if (*reply == '\n')
return (yes);
if (*reply == 'n')
return (0);
else if (*reply == 'y')
return (1);
else {
if (*reply != '?') incorrect(reply);
bshelp("buy the current offer");
}
}
/*NOTREACHED*/
}
/* sell -- called in every buy-sell step if we're playing a seller.
Must return 1 to request a sell, or 0 to pass.
Must return 0 if nobuysell>0. */
int
sell()
{
int nexttoken;
char * reply;
char prompt[15];
#ifdef TIME_OUT_BS
timeleft = TIME_OUT_BS;
#else
timeleft = timeout*2/3;
#endif
if (nobuysell&1) {
while (!ready("nothing to trade")) ;
return (0);
}
if (nobuysell&2) {
while (!ready("nothing to sell")) ;
return (0);
}
if (nobuysell&4) {
while (!ready("not offerer")) ;
return (0);
}
nexttoken = token[mytrades+1];
while(1) {
if (nexttoken>=cbid && unwise) {
if (ready("unwise to sell"))
return (0);
else
continue;
}
sprintf(prompt,"sell at %d [%c]",cbid,yes?'y':'n');
reply = ask(prompt);
if (*reply == EOS) continue;
if (*reply == '\n')
return (yes);
if (*reply == 'n' || *reply == '0')
return (0);
else if (*reply == 'y' || *reply == '1')
return (1);
else {
if (*reply != '?') incorrect(reply);
bshelp("sell at the current bid value");
}
}
/*NOTREACHED*/
}
/* --------- miscellaneous support routines for human interface --------- */
static void
bohelp(string)
char * string;
{
printf("To make a%s %s, type your %s value.\n",(*string=='o')?"n":"",
string,string);
puts("To pass, type 'n' or just press RETURN.");
puts("Type 'help' for more information.\n");
}
static void
bshelp(string)
char * string;
{
printf("Type 'y' to request to %s.\n",string);
puts("Type 'n' to pass.");
printf("Just pressing RETURN is presently equivalent to '%c'.\n",
yes?'y':'n');
puts("Type 'help' for more information.\n");
}
static char *
ask(prompt)
char *prompt;
/*
* Asks 'prompt? ' and waits for reply or timeout.
* Includes processing of user commands.
* Returns reply string or "\n" if timeout.
*/
{
char tempchar;
waitforreturn = 0;
if (passflag) {
if (kbhit()) {
tempchar = getchar();
if (tempchar == 'P' || tempchar == 'p') {
passflag = 0;
return response(prompt,1,0);
}
}
puts(prompt);
return newline;
}
return response(prompt,1,0);
}
static int
ready(prompt)
char * prompt;
/*
* Says 'prompt> ' and waits for response or timeout.
* Includes processing of user commands.
* Returns 1 for correct reply/timeout, 0 for anything else.
*/
{
char * reply;
waitforreturn = 0;
if (fastflag || passflag) {
puts(prompt);
return 1;
}
reply = response(prompt,0,timeleft-5);
if (*reply == EOS) return 0;
if (*reply == '\n') return 1;
if (*reply != '?') incorrect(reply);
puts("A message ending in '>' is just informational.");
puts("Press RETURN to continue before the delay expires.");
puts(
"You can prevent any wait at '>' prompts by setting the 'f' (fast) flag.");
puts("Type 'help' for more information.\n");
return 0;
}
static char *
response(prompt,quest,stoptime)
char *prompt;
int quest; /* 1 for ?, 0 for > */
int stoptime;
/*
* Writes prompt, gets reply or times out.
* Displays a . every second (or a : in the last five seconds) if DOTS.
* Processes options and user commands (e.h. 'help', 's').
* Returns user's reply (past any options) if any.
* Returns "\0" if no reply yet, but possible change of options etc.
* Returns '\n' if timeout occurs.
* Quits if reply is 'quit'.
*/
{
int done,value;
char * lptr;
/* put out the prompt */
fputs(prompt,stdout);
if (quest)
fputs("? ",stdout);
else
fputs("> ",stdout);
fflush(stdout);
/* get reply */
getreply(linebuf,LINESIZE,stoptime);
/* test for '\n', 'quit', 'help', literal quote */
if (linebuf[0] == '\n')
return linebuf;
if (strcmp(linebuf,"quit\n")==0)
error("");
if (strcmp(linebuf,"help\n")==0) {
help();
return none;
}
if (linebuf[0] == '\'') {
puts("Don't type the quotes (') themselves.");
return none;
}
/* process single letter options and commands */
lptr = linebuf;
value = 1;
done = 0;
do {
switch (*lptr++) {
case ' ':
case '\t':
case '\n':
break;
case '-':
value = 0;
break;
case '+':
value = 1;
break;
case 'a':
yes = value;
break;
case 'P':
passflag = value;
break;
case 'f':
fastflag = value;
break;
case 'u':
unwise = value;
break;
case 'w':
waitflag = value;
break;
case 's':
case 'c':
case 't':
showcurrent();
break;
case '$':
case 'p':
nl();
showprices();
break;
case 'h':
showhist(MAXHIST);
break;
default:
done++;
}
} while (!done) ;
/* return rest of string (EOS if none) */
return (--lptr);
}
static void
getreply(buf,size,stoptime)
char *buf;
int size;
int stoptime;
/*
* Gets user's response, or times out.
* Puts out .'s or :'s.
* Deals with simple local editing (BS or DEL).
*/
{
#ifdef TIMEOUT
register int c;
char * ptr;
#endif
/* discard pending input */
#ifdef UNIX
#ifdef TTY
ioctl(fileno(stdin),TIOCFLUSH,&one);
#else
ioctl(fileno(stdin),TCFLSH,0);
#endif
#endif
#ifdef DOS_OR_T3
while (kbhit())
getch();
#endif
#ifdef THINKC4
fflush(stdin);
#endif
#ifdef VMS
queued = (-1); /* only works if timeout enabled */
#endif
#ifdef TIMEOUT
if (waitflag || timeout==9999) {
if (noblock)
resetterm();
fgets(buf,size,stdin);
return;
}
if (!noblock)
setnoblock();
if (stoptime<0) stoptime = 0;
ptr = buf;
while (1) {
/* sleep a second */
sleep(1);
/* read in available characters */
#ifdef UNIX
errno = 0;
#endif
while( (c = termchar()) != EOF && c != '\n'
#ifdef THINKC
&& c != '\r' && c != 3) {
#else
&& c != '\r') {
#endif
if (c == INTRCHAR)
error("interrupt");
else if (c == BS || c == DEL) {
if (ptr > buf) {
if (c == DEL) {
putnflush(BS);
putnflush(BS);
}
putnflush(' ');
putnflush(BS);
--ptr;
++size;
}
}
else if (size > 2) {
*(ptr++) = c;
--size;
}
}
/* message is complete if the last was \n or other terminator */
if (c != EOF) {
if (c != '\n') putnflush('\n');
*(ptr++) = '\n';
*(ptr) = EOS;
return;
}
#ifdef UNIX
/* check for unexpected error */
#ifdef EAGAIN
if ( errno != 0 && errno != EWOULDBLOCK && errno != EAGAIN) {
#else
if ( errno != 0 && errno != EWOULDBLOCK) {
#endif
error("termchar failure");
}
#endif
/* put out . or : if no characters yet and DOTS defined */
#ifdef DOTS
if (ptr == buf) {
if (timeleft-stoptime>6)
putnflush('.');
else if (timeleft-stoptime>1)
putnflush(':');
}
#endif
/* give up and return "\n" if timed out */
if (--timeleft <= stoptime) {
buf[0] = '\n';
buf[1] = EOS;
puts("!");
fflush(stdout);
return;
}
}
#else
fgets(buf,size,stdin);
#endif
}
#ifdef TIMEOUT
static void
putnflush(c) /* puts out one character and flushes */
int c;
{
putchar(c);
fflush(stdout);
}
static int
termchar()
/*
* Reads one character from the terminal if there is one,
* otherwise returns EOF.
*/
{
int c = EOF;
#ifdef UNIX
char buf[1];
if (read(0,buf,1) == 1)
c = buf[0]&0177;
#endif
#ifdef DOS_OR_T3
if (kbhit())
c = getche();
#endif
#ifdef THINKC4
c = getchar();
if (c == EOF) c = getchar();
if (c == EOF) c = getchar();
if (c == EOF) c = getchar();
if (c != EOF) putchar(c); /* do our own echo -- CBREAK mode doesn't work */
#endif
#ifdef VMS
static char buf[2];
static struct ios_block iosb;
if (queued<=0) {
if (sys$qio(0,dcl_chan,
IO$_READVBLK|IO$M_NOFILTR|((queued<0)?IO$M_PURGE:0),
&iosb,0,0,buf,1,0,0,0,0) != 1) error("qio failure");
queued = 1;
}
if (iosb.iostat == 1) {
c = buf[0];
queued = 0;
}
else if (iosb.iostat)
error("i/o error");
#endif
return c;
}
#endif
static void
incorrect(reply) /* Puts out 'Incorrect response' message */
char * reply;
{
printf("%c** Incorrect response: %s",BELL,reply);
}
static void
help() /* Copies 'helpfile' to terminal */
{
FILE * helpfile;
helpfile = fopen("helpfile","r");
if (helpfile == NULL) {
puts("helpfile not available");
return;
}
while(fgets(linebuf,LINESIZE,helpfile) != NULL)
if (linebuf[0] != '#')
fputs(linebuf,stdout);
fclose(helpfile);
}
static void
showhist(nlines) /* Display history of nlines recent steps in this period */
int nlines;
{
#ifndef HISTORY
puts("history not available");
#else
register int i,j,l;
int ll;
int tt;
int anytrade;
int prevcbid,prevcoffer,prevtt;
unsigned int * hist;
unsigned int code;
char suffix[3];
int tprice,lfirst,value;
if (nlines <= 0) return;
if (nlines >= MAXHIST) nlines = MAXHIST;
if (last < 0) {
puts("no history yet in this period");
return;
}
printf("\nt ");
for (i=1; i<=nbuyers; i++)
if (i == id && role == 1)
fputs(" YOU ",stdout);
else
printf(" B%d ",i);
for (i=1; i<=nsellers; i++)
if (i == id && role == 2)
fputs(" YOU ",stdout);
else
printf(" S%d ",i);
puts(" price");
lfirst = last+1-nlines;
if (lfirst<0) lfirst = 0;
prevcbid = 0;
prevcoffer = 0;
prevtt = 0;
for (ll=lfirst; ll<=last; ll++) {
l = ll%MAXHIST;
hist = histlist[l];
tt = tlist[l]&TIMEMASK;
if (tt==0 && prevtt>0 && ll<last &&
(tlist[(ll+1)%MAXHIST]&TIMEMASK)==prevtt+2) {
tt = prevtt+1;
tlist[l] |= tt; /* fix t/?/t+2 sequence */
}
if (tt > 0)
printf("%-3d",tt);
else
fputs("? ",stdout);
if (tlist[l]&(NOBOHIST|NOBSHIST))
putchar('*');
else if (tt!=prevtt+1 && tt>0 && prevtt>0)
putchar('!');
else
putchar(' ');
prevtt = tt;
tprice = 0;
anytrade = 0;
for (i=1; i<=nbuyers+nsellers; i++) {
code = hist[i-1];
value = (code&BOMASK);
j = 0;
if (code&CURRENT) {
if (value == 0) {
if (i<=nbuyers) value = prevcbid;
else value = prevcoffer;
suffix[j++] = '#';
}
else {
if (i<=nbuyers) prevcbid = value;
else prevcoffer = value;
suffix[j++] = '*';
}
}
if (code&SFLAG) {
suffix[j++] = SELLCHAR;
++anytrade;
}
else if (code&BFLAG) {
suffix[j++] = BUYCHAR;
++anytrade;
}
if (j==0) suffix[0] = ' ';
if (j<=1) suffix[1] = ' ';
suffix[2] = EOS;
if (value > 0)
printf("%5d%s",value,suffix);
else
printf(" %s",suffix);
if (j==2) {
if (i <= nbuyers)
{ if (code&SFLAG) tprice = value; }
else
{ if (code&BFLAG) tprice = value; }
}
}
if (tprice > 0)
printf(" %5d\n",tprice);
else if (anytrade)
puts(" ?");
else
nl();
}
nl();
#endif
}
#ifdef FILEBASED
/* --------------------- save and restore routines ----------------------
* The following two routines are used to save and restore the program's
* variables between invocations if the FILEBASED method is used.
*/
extern FILE * savefile;
void
savedata() /* write the save file */
{
extern void writearray();
/* added for human interface */
#ifdef HISTORY
register int i,j;
int lastj;
unsigned int * hist;
#endif
fprintf(savefile,"%d %d %d %d %d %d %d %d %d\n",
nplayers,nbuyers,nsellers,nrounds,nperiods,ntimes,
minprice,maxprice,gameid);
fprintf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
r,p,t,cbid,coffer,bidder,offerer,nbids,noffers,bstype,
price,buyer,seller,ntrades,lasttime);
fprintf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
id,role,timeout,ntokens,mytrades,mylasttime,pprofit,
rprofit,gprofit,nobidoff,bo,nobuysell,bs,late,noblock);
writearray(bnumber,nbuyers);
writearray(snumber,nsellers);
writearray(bids,nbuyers);
writearray(offers,nsellers);
writearray(btrades,nbuyers);
writearray(strades,nsellers);
writearray(prices,ntrades);
writearray(token,ntokens);
writearray(tradelist,p);
writearray(profitlist,p);
/* added for human interface */
fprintf(savefile,"%d %d %d %d %d\n",unwise,yes,passflag,fastflag,waitflag);
#ifdef HISTORY
fprintf(savefile,"%d\n",last);
if (last>=MAXHIST) lastj = MAXHIST-1;
else lastj = last;
for (j=0; j<=lastj; j++) {
hist = histlist[j];
fprintf(savefile,"%d ",tlist[j]);
for (i=0; i<nbuyers+nsellers; i++)
fprintf(savefile,"%u ",hist[i]);
putc('\n',savefile);
}
#endif
}
void
retrievedata() /* read the save file */
{
extern void readarray();
/* added for human interface */
#ifdef HISTORY
register int i,j;
int lastj;
unsigned int * hist;
#endif
fscanf(savefile,"%d %d %d %d %d %d %d %d %d",
&nplayers,&nbuyers,&nsellers,&nrounds,&nperiods,&ntimes,
&minprice,&maxprice,&gameid);
fscanf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
&r,&p,&t,&cbid,&coffer,&bidder,&offerer,&nbids,&noffers,&bstype,
&price,&buyer,&seller,&ntrades,&lasttime);
fscanf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
&id,&role,&timeout,&ntokens,&mytrades,&mylasttime,&pprofit,
&rprofit,&gprofit,&nobidoff,&bo,&nobuysell,&bs,&late,&noblock);
readarray(bnumber,nbuyers);
readarray(snumber,nsellers);
readarray(bids,nbuyers);
readarray(offers,nsellers);
readarray(btrades,nbuyers);
readarray(strades,nsellers);
readarray(prices,ntrades);
readarray(token,ntokens);
readarray(tradelist,p);
readarray(profitlist,p);
/* added for human interface */
fscanf(savefile,"%d %d %d %d %d\n",&unwise,&yes,&passflag,&fastflag,
&waitflag);
#ifdef HISTORY
fscanf(savefile,"%d",&last);
if (last>=MAXHIST) lastj = MAXHIST-1;
else lastj = last;
for (j=0; j<=lastj; j++) {
hist = histlist[j];
fscanf(savefile,"%d ",tlist+j);
for (i=0; i<nbuyers+nsellers; i++)
fscanf(savefile,"%u ",hist+i);
}
#endif
}
#endif
/* get user's limits etc */
void
getparams(maxplayers,maxrounds,maxperiods,maxtimes,maxtokens,roles,playernum)
int *maxplayers, *maxrounds, *maxperiods, *maxtimes, *maxtokens;
int *roles, *playernum;
{
*maxplayers = MAXPLAYERS;
*maxrounds = MAXROUNDS;
*maxperiods = MAXPERIODS;
*maxtimes = MAXTIMES;
*maxtokens = MAXTOKENS;
*roles = ROLES;
*playernum = PLAYERNUMBER;
}
/* ------------- pre-game routines for INETBASED case ------------- */
#ifdef INETBASED
void
getpname(name,maxlen)
char *name;
int maxlen;
/*
* Get player name.
* Asks user for name, copies it into name with trailing \n\0.
*/
{
int len;
do {
fputs("Enter your name: ",stderr);
if (fgets(linebuf,LINESIZE,stdin) == NULL)
error("read failed (try 'reset')");
if (strcmp(linebuf,"quit\n")==0)
exit(GOODEXIT);
len = strlen(linebuf);
if (len >= maxlen) {
fputs("** too long -- shorten\n",stderr);
len = 0;
}
} while (len <= 1) ;
strcpy(name,linebuf);
}
void
getpassword(password,maxlen)
char *password;
int maxlen;
{
int len;
char linebuf[200];
do {
fputs("Please enter your password: ",stderr);
if (fgets(linebuf,LINESIZE,stdin) == NULL)
error("read failed (try 'reset')");
if (strcmp(linebuf,"quit\n")==0)
exit(0);
len = strlen(linebuf);
if (len >= maxlen-1) {
fputs("** too long -- shorten\n",stderr);
len = 0;
}
} while (len <= 1);
sprintf(password, "#%s",linebuf);
}
int
getrole()
{
return 3;
}
#endif
/*
* Routines for non-blocking terminal input. These put the terminal
* in a non-standard state, but try hard to restore the old state
* before exit or abort. If the program is killed or aborted by
* other than ^C the changed state may remain; use the Unix 'reset'
* command to fix it (if the shell doesn't log you out!).
* Specifically the terminal should be made to:
* 1. Not block if there are no characters available.
* 2. Return individual characters as soon as available.
* 3. Not process erase or kill characters (implied by 2).
* 4. Echo control charaacters as is, not as ^x.
* 5. Not recognize ^C as an interrupt.
* Note that there are three different Unix ways of doing this. All
* are implemented here, and are selected by defining TTY, TERMIO, or
* TERMIOS depending on the system. See the #define's near the start
* of this file.
* TTY Old unix terminal handler.
* TERMIO System V standard, and some others.
* TERMIOS New BSD handler.
* Also note that FCNTL is needed on some systems to implement no-blocking.
*/
#ifdef UNOBLOCK
static int save1,save2,save3;
termstruct mytermios;
#ifdef TTY
struct tchars spchars;
static int lmode;
#endif
#endif
void
setnoblock() /* set up terminal for non-blocking input */
{
#ifdef UNOBLOCK
int fdin = fileno(stdin);
#ifdef FCNTL
fcntl(fdin,F_SETFL,O_NDELAY); /* no block */
#endif
ioctl(fdin,GETTERM,&mytermios);
#ifdef TTY
save1 = mytermios.sg_flags;
mytermios.sg_flags |= CBREAK; /* no input processing */
#else
save1 = mytermios.c_lflag;
save2 = mytermios.c_cc[VMIN];
save3 = mytermios.c_cc[VTIME];
mytermios.c_lflag = ECHO; /* no canon, no signals */
mytermios.c_cc[VMIN] = 0; /* MIN = 0 */
mytermios.c_cc[VTIME] = 0; /* TIME = 0 */
#endif
ioctl(fdin,SETTERM,&mytermios);
#ifdef TTY
ioctl(fdin,TIOCGETC,&spchars);
save2 = spchars.t_intrc;
spchars.t_intrc = '\377'; /* no interrupt */
ioctl(fdin,TIOCSETC,&spchars);
ioctl(fdin,TIOCLGET,&save3);
lmode = save3&~LCTLECH; /* no ^x echo */
ioctl(fdin,TIOCLSET,&lmode);
#endif
#endif
#ifdef THINKC4
csetmode(C_RAW,stdin);
#endif
#ifdef VMS
#ifdef TIMEOUT
static $DESCRIPTOR(ttyname,"SYS$INPUT");
if (sys$assign(&ttyname,&dcl_chan,0,0) != 1)
error("can't assign SYS$INPUT");
#endif
#endif
noblock = 1;
}
void
resetterm() /* restore previous terminal state */
{
#ifdef UNOBLOCK
int fdin = fileno(stdin);
ioctl(fdin,GETTERM,&mytermios);
#ifdef TTY
mytermios.sg_flags = save1;
#else
mytermios.c_lflag = save1;
mytermios.c_cc[VMIN] = save2;
mytermios.c_cc[VTIME] = save3;
#endif
ioctl(fdin,SETTERM,&mytermios);
#ifdef TTY
ioctl(fdin,TIOCGETC,&spchars);
spchars.t_intrc = save2;
ioctl(fdin,TIOCSETC,&spchars);
ioctl(fdin,TIOCLSET,&save3);
#endif
#ifdef FCNTL
fcntl(fdin,F_SETFL,0);
#endif
#endif
#ifdef THINKC4
csetmode(C_ECHO,stdin);
#endif
noblock = 0;
}
#ifdef QUICKC
static void
sleep(secs) /* sleep() routine for QUICKC */
int secs;
{
long start,end,ltime;
start = time(<ime);
end = start + secs;
do {;} while(time(<ime)<end);
}
#endif
#ifdef UNIX
/* For BSD 4.2 compatibility */
#ifndef FD_ZERO
typedef struct fd_set_tag {
long masks[9];
} DESCR_MASK;
#define FD_SET(n, p) ((p)->masks[(n) / 32] |= (1 << ((n) % 32)))
#define FD_CLR(n, p) ((p)->masks[(n) / 32] &= ~(1 << ((n) % 32)))
#define FD_ISSET(n, p) ((p)->masks[(n) / 32] & (1 << ((n) % 32)))
#define FD_ZERO(p) bzero((p), sizeof(*(p)))
#else
typedef fd_set DESCR_MASK;
#endif
int input_waiting(fd)
int fd;
{
struct timeval tv;
DESCR_MASK readers;
tv.tv_sec = tv.tv_usec = 0;
FD_ZERO(&readers);
FD_SET(fd, &readers);
return select(fd + 1, &readers, (DESCR_MASK *) NULL,
(DESCR_MASK *) NULL, &tv);
}
int kbhit() { return input_waiting(0); }
#endif /* UNIX */